#ifndef PRUEBAINDICEHASHEXTENSIBLE_H_
#define PRUEBAINDICEHASHEXTENSIBLE_H_

#define private public

#include "../IndiceHashExtensible.h"
#include "../includes.h"
#include "ClaveAlumno.h"
#include "../includes.h"
#include "../Cuba.h"
#include "../ClaveDatoCuba.h"
#include "../DatoCuba.h"
#include "../funciones.h"

using namespace Toolkit;

//void pruebaRecuperarDirectorio()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - pruebaRecuperarDirectorio"<<endl;
//	TipoSerializacion tSerializacion = BINARIO;
//	IndiceHashExtensible *hashExtensible = new IndiceHashExtensible(500, "", "hash");
//
//	//ingreso claves al azar
//	int cantidadClaves = 200;
//
//	for(int i = 0; i < cantidadClaves; i++)
//	{
//		ClaveAlumno clave(i*7, tSerializacion);
//		hashExtensible->insertar(clave, 20*i);
//	}
//
//	int cantidadElementos = hashExtensible->directorio.size();
//
//	for (int i = 0; i < cantidadElementos ; i++)
//	{
//		if ((i % 5) == 0)
//		{
//			cerr << endl;
//		}
//
//		cerr << "directorio[" << i << "]=" << hashExtensible->directorio[i] << " " ;
//	}
//
//	delete hashExtensible;
//
//	hashExtensible = new IndiceHashExtensible("", "hash");
//
//	int cantidadElementos2 = hashExtensible->directorio.size();
//
//	for (int i = 0; i < cantidadElementos2 ; i++)
//	{
//		if ((i % 5) == 0)
//		{
//			cerr << endl;
//		}
//
//		cerr << "directorio[" << i << "]=" << hashExtensible->directorio[i] << " " ;
//	}
//
//	delete hashExtensible;
//
//	hashExtensible = new IndiceHashExtensible("", "hash");
//
//	int cantidadElementos3 = hashExtensible->directorio.size();
//
//	for (int i = 0; i < cantidadElementos3 ; i++)
//	{
//		if ((i % 5) == 0)
//		{
//			cerr << endl;
//		}
//
//		cerr << "directorio[" << i << "]=" << hashExtensible->directorio[i] << " " ;
//	}
//}
//
//void pruebaDividirYCombinarCubas()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - Dividir Cubas"<<endl;
//	TipoSerializacion tSerializacion = BINARIO;
//	IndiceHashExtensible hashExtensible(1000, "", "hash");
//	hashExtensible.profundidad = 1;
//
//	Cuba cubaAdividir(1000, tSerializacion);
//
//	int cantidadRegistros = 7;
//	for (int i = 0; i < cantidadRegistros; i++)
//	{
//		ClaveAlumno claveAlumno(i, tSerializacion);
//		cout << "la direccion es: " << hashExtensible.crearDireccion(claveAlumno) << endl;
//		Registro *registro = new Registro(tSerializacion);
//		unsigned long int  hola = 10*i;
//		DatoCuba datoCuba(hola,claveAlumno, tSerializacion);
//		registro->setDato(datoCuba);
//		cubaAdividir.agregar(registro);
//	}
//
//	unsigned int inicio, fin;
//	Cuba* cubaNueva = hashExtensible.dividirCuba(cubaAdividir, inicio, fin);
//
//	cout << "antes, cuba nuevo serializacion: " << cubaNueva->getTamanoSerializacion() << endl;
//	cout << "antes, cuba nueva cantidadElementos:" << cubaNueva->cantElementos() << endl;
//	cout << "antes, cuba vieja cantidadElementos:" << cubaAdividir.cantElementos() << endl;
//
//	cubaNueva->combinar(cubaAdividir);
//
//	cout << "despues, cuba nueva serializacion: " << cubaNueva->getTamanoSerializacion() << endl;
//	cout << "despues, cuba nueva cantidadElementos: " << cubaNueva->cantElementos() << endl;
//	cout << "despues, cuba vieja cantidadElementos: " << cubaAdividir.cantElementos() << endl;
//
//	delete cubaNueva;
//
//	cerr<<"Termina prueba"<<endl;
//}
//
//void PruebaActualizarCubaEnAlmacenamiento()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - Actualizar Cuba En Almacenamiento"<<endl;
//	TipoSerializacion tSerializacion = TEXTO;
//	IndiceHashExtensible hashExtensible(150, "", "hash");
//
//	ClaveAlumno claveAlumno(4940, tSerializacion);
//
//	//me devuelve la unica cuba y vacia
//	Cuba* cubaAmodificar = hashExtensible.buscarCuba(claveAlumno);
//
//	//creo un registro
//	int posicionBloque = 20;
//	Registro *registro = new Registro(tSerializacion);
//	DatoCuba datoCuba(posicionBloque, claveAlumno,tSerializacion);
//	ClaveDatoCuba claveDatoCuba(datoCuba, tSerializacion);
//	registro->setDato(datoCuba);
//
//	//inserto claveAlumno a la cubaModificada
//	cubaAmodificar->agregar(registro, claveDatoCuba);
//
//	hashExtensible.actualizarCubaEnAlmacenamiento(*cubaAmodificar);
//
//	Cuba* Cubo = hashExtensible.buscarCuba(claveAlumno);
//
//	Registro *lala = (Registro*)Cubo->popBack();
//
//	DatoCuba* datoCubalala = (DatoCuba*)lala->clonarDato();
//
//	if (posicionBloque == datoCubalala->getPosicionBloque())
//	{
//		cout << "funciona Actualizar Cuba" << endl;
//	} else {
//		cout << "no funciona Actualizar Cuba" << endl;
//	}
//	cerr<<"Termina prueba"<<endl;
//}
//
//void pruebaExpandir()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - Expandir"<<endl;
//	IndiceHashExtensible hashExtensible(150,"", "hash");
//
//	hashExtensible.expandirDirectorio();
//	hashExtensible.directorio[1] = 1;
//	hashExtensible.expandirDirectorio();
//	hashExtensible.directorio[1] = 2;
//	hashExtensible.expandirDirectorio();
//
//	for(int i = 0; i < 8; i++)
//	{
//		cout << hashExtensible.directorio[i];
//	}
//	cerr<<"Termina prueba"<<endl;
//}
//
//void pruebaContraer()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - Contraer"<<endl;
//	IndiceHashExtensible hashExtensible(150,"", "hash");
//
//	hashExtensible.expandirDirectorio();
//	hashExtensible.directorio[1] = 1;
//	hashExtensible.expandirDirectorio();
//	hashExtensible.expandirDirectorio();
//
//	hashExtensible.contraerDirectorio();
//	hashExtensible.contraerDirectorio();
//
//	for(int i = 0; i < 2; i++)
//	{
//		cout << hashExtensible.directorio[i];
//	}
//	cerr<<"Termina prueba"<<endl;
//}
//
//void pruebaCalcularRangoDirecciones()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - Calcular Rango Direcciones"<<endl;
//	TipoSerializacion tSerializacion = TEXTO;
//	IndiceHashExtensible hashExtensible(150, "", "hash");
//
//	int tamanoBloque = 512;
//	Cuba cuba(tamanoBloque, tSerializacion);
//
//	unsigned int comienzo, fin;
//	hashExtensible.calcularRangoDirecciones(cuba, comienzo, fin);
//
//	if ((comienzo == 0) && (fin == 1 )){
//		cout << "prueba CalcularRango en cuba vacia exitosa \n";
//	} else {
//		cout << "prueba CalcularRango en cuba vacia fallida \n";
//	}
//
//	hashExtensible.profundidad = 4;
//
//	ClaveAlumno claveAlumno(88240, tSerializacion);
//	Registro *registro = new Registro(tSerializacion);
//	DatoCuba datoCuba(20, claveAlumno,tSerializacion);
//	ClaveDatoCuba claveDatoCuba(datoCuba, tSerializacion);
//	registro->setDato(datoCuba);
//
//	cuba.agregar(registro, claveDatoCuba);
//
//	unsigned int direccion = hashExtensible.crearDireccion(claveAlumno);
//	cuba.setProfundidad(2);
//
//	hashExtensible.calcularRangoDirecciones(cuba, comienzo, fin);
//
//	if ((direccion == comienzo) && (direccion == (fin -4)))
//	{
//		cout << "prueba CalcularRango en cuba llena exitosa \n";
//	} else {
//		cout << "prueba CalcularRango en cuba llena fallida \n";
//	}
//	cerr<<"Termina prueba"<<endl;
//}
//
//void pruebaInsertarMasivo()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - Insertar Masivo"<<endl;
//	TipoSerializacion tSerializacion = BINARIO;
//	IndiceHashExtensible hashExtensible(3000, "", "hash");
//
//	int cantidadClaves = 1000;
//
//	for(int i = 0; i < cantidadClaves; i++)
//	{
//		ClaveAlumno clave(i*5, tSerializacion);
//		hashExtensible.insertar(clave, 20*i);
//	}
//
//	ClaveAlumno clave(30, tSerializacion);
//	unsigned long int posDevuelta;
//	hashExtensible.buscar(clave, posDevuelta);
//
//	cerr << "la posicion devuelta es: " << posDevuelta << endl;
//	cerr << "la profundidad es: " << hashExtensible.profundidad << endl;
//
//	int cantidadElementos = pow (2,hashExtensible.profundidad);
//
//	for (int i = 0; i < cantidadElementos ; i++)
//	{
//		cerr << "en la posicion " << i << " , hay: " << hashExtensible.directorio[i] << endl;
//	}
//
//	Registro reg1(tSerializacion);
//	ClaveAlumno claveAl( 85996,tSerializacion);
//	DatoCuba datoC(1234,claveAl, tSerializacion);
//
//	reg1.setDato(datoC);
//
//	cerr<<"Tamaño serializacion: "<<reg1.getTamanoSerializacion()<<endl;
//	cerr<<"Termina prueba"<<endl;
//
//}
//
//void pruebaKill()
//{
//	cerr<<"Comienza prueba: Indexado Hash Extensible - Prueba de stress"<<endl;
//	TipoSerializacion tSerializacion = BINARIO;
//	IndiceHashExtensible hashExtensible(90,"", "hash");
//	int cantidadClaves = 50;
//
//	// Inserto cantidadClaves en el indice, con una posicion de bloque determinada
//	for(int i = 0; i < cantidadClaves; i++)
//	{
//		ClaveAlumno clave(i*5, tSerializacion);
//		hashExtensible.insertar(clave, 20*i);
//	}
//
//	for (unsigned int i = 0; i < hashExtensible.directorio.size() ; i++)
//	{
//		cerr << " posicion " << i << " : " << hashExtensible.directorio[i];
//	}
//
//	for(int i = 0; i < cantidadClaves; i ++)
//	{
//		ClaveAlumno clave(i*5, tSerializacion);
//		hashExtensible.eliminar(clave);
//	}
//
//	cerr << "profundidad hash: " << hashExtensible.profundidad;
//	cerr << endl;
//
//	for (unsigned int i = 0; i < hashExtensible.directorio.size() ; i++)
//	{
//		cerr << " posicion " << i << " : " << hashExtensible.directorio[i];
//	}
//
//	ClaveAlumno clave(5, tSerializacion);
//
//	DatoCuba datoCuba(20, clave, tSerializacion);
//
//}

/**
 * 1. Inserto X cantidad de claves
 * 2. P0 = Las busca y verifica que esten -> g00d
 * 3. P1 = Busco claves que no deberian estar en el indice. -> g00d
 * 4. P2 = Elimino pares, busco pares -> funciona con 300 claves (funciona con 1000)
 * 5. P3 = busco impares -> funciona con 300 claves (funciona con 1000)
 * 6. P4 = elimino impares, busco impares // no se rompe con el ingreso de 500 claves, pero si con 1000
 */
void pruebaHashingBurnIn()
{
	cerr<<"Comienza prueba: Indexado Hash Extensible - Prueba de stress"<<endl;
	TipoSerializacion tSerializacion = BINARIO;
	IndiceHashExtensible hashExtensible(200, "", "hash");

	int cantidadClaves = 4000;

	// Inserto cantidadClaves en el indice, con una posicion de bloque determinada
	for(int i = 0; i < cantidadClaves; i++)
	{
		ClaveAlumno clave(i*5, tSerializacion);
		hashExtensible.insertar(clave, 20*i);
	}

	int f = 0;
	// Busco las claves q deberia estar en el indice
	for(int i = 0; i < cantidadClaves; i++)
	{
		ClaveAlumno clave(i*5, tSerializacion);
		unsigned long int posDevuelta;
		hashExtensible.buscar(clave, posDevuelta);
		unsigned int lala = i*20;
		if (posDevuelta != lala)
		{
			f++;
			cerr << "P0: No se encuentra la clave q deberia encontrarse" <<endl;
			cerr << "Deberia devolver "<<i*20<<" y se devuelve: " << posDevuelta << endl;
		}
	}

	if (f == 0)
	{
		cerr << "P0: Busco claves que deberian estar y las encuentro :D" <<endl;
	}

	// Busco claves q NO deberian estar en el indice
	int n = 0;
	for(int i = 0; i < cantidadClaves; i++)
	{
		ClaveAlumno clave(i*9999, tSerializacion);
		unsigned long int posDevuelta;
		hashExtensible.buscar(clave, posDevuelta);
		if (posDevuelta != 0)
		{
			n++;
			cerr << "P1: No se encuentra la clave q deberia encontrarse" <<endl;
			cerr << "\t Se deberia devolver"<<0<<" y se devuelve: " << posDevuelta << endl;
		}
	}

	if (n == 0)
	{
		cerr << "P1: Busco claves que NO deberian estar y las NO encuentro :D" <<endl;
	}

	int cantidadParesEliminadas  = 0;
	// Elimino claves pares
	for(int i = 0; i < cantidadClaves; i += 2)
	{
		ClaveAlumno clave(i*5, tSerializacion);
		cantidadParesEliminadas++;
		hashExtensible.eliminar(clave);
	}

	int k = 0;

	// Busco claves pares ya eliminadas
	for(int i = 0; i < cantidadClaves; i+=2)
	{
		ClaveAlumno clave(i*5, tSerializacion);
		unsigned long int posDevuelta;
		hashExtensible.buscar(clave, posDevuelta);

		if (posDevuelta != 0)
		{
			k++;
			cerr << "P2: Encuentro una clave que no deberia" <<endl;
			cerr << "\t Se deberia devolver "<< 0 <<" y se devuelve: " << posDevuelta << endl;
		}
	}

	if (k == 0){
		cerr << "P2: Elimino claves pares y no las encuentro :D" <<endl;
	}

	int m = 0;
	for(int i = 1; i < cantidadClaves; i += 2)
	{
		ClaveAlumno clave(i*5, tSerializacion);
		unsigned long int posDevuelta;
		hashExtensible.buscar(clave, posDevuelta);
		if (posDevuelta != (i*20))
		{
			m++;
			cerr << "P3: No encuentro una clave que deberia" <<endl;
			cerr << "\t Deberia devolver"<<20*i<<" y devuelve: " << posDevuelta << endl;
		}
	}

	if (m == 0)
	{
		cerr << "P3: Elimine las pares y todavia encuentro las impares :D" <<endl;
	}

	int clavesImpares = 0;
	//borro claves impares
	for(int i = 1; i < cantidadClaves; i += 2)
	{
		ClaveAlumno clave(i*5, tSerializacion);
		clavesImpares++;
		hashExtensible.eliminar(clave);
	}

	int j = 0;
	// busco impares
	for(int i = 1; i < cantidadClaves; i += 2)
	{

		ClaveAlumno clave(i*5, tSerializacion);
		unsigned long int posDevuelta;
		hashExtensible.buscar(clave, posDevuelta);
		if (posDevuelta != 0)
		{
			j++;
			cerr<<"iteracion "<<i<<endl;
			cerr << "P4: Se encuentra una clave q no deberia estar" <<endl;
			cerr << "\t Se deberia devolver"<<0<<" y se devuelve: " << posDevuelta << endl;
		}
	}

	if (j == 0)
	{
		cerr << endl << "P4: Elimino claves impares y no las encuentro :D" <<endl;
	}

	cerr<<"Termina prueba"<<endl;
}

#endif /* PRUEBAINDICEHASHEXTENSIBLE_H_ */
